package com.vgemv.jsutilitysdk.Request.JsRequestManager;


import android.content.Context;

import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;

import com.google.gson.Gson;
import com.vgemv.jsutilitysdk.JsJsonManager.JsJsonManager;
import com.vgemv.jsutilitysdk.Request.JsRequestInterface;
import com.vgemv.jsutilitysdk.JsThread.JsThreadManager;
import com.vgemv.jsutilitysdk.SharedPreference.JsSharedPreferencesManager;
import com.vgemv.jsutilitysdk.Request.JsRequestManager.JsRequestManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * JsRequestManager.
 * Funciton:
 *  Network reqeust.
 *
 * Dependency:
 *  Gson
 *  JsSharedPreferencesManager
 *
 */
public class JsRequestManager implements JsRequestInterface {

    final static String cookiesKey = "cookiesKey";
    public String serverAddress = null;

    private static JsRequestManager _sharedInstance;

    private OkHttpClient mDefaultClient;

    private JsSharedPreferencesManager mSpManager;

    private Gson mGson_sharedJsonParser;

    private Context mContext;

    //用来存储cookie的map. 这样只能存储在内存中,第二次进入就没了.
    private HashMap<String, List<Cookie>> mMap_cookieStore = new HashMap<>();

    public boolean mb_isSaveCookieToEp = true;

    public static JsRequestManager sharedInstance() {
        return _sharedInstance;
    }

    public static void initClass(Context context,boolean isSaveCookie) {
        _sharedInstance = new JsRequestManager(context,isSaveCookie);
    }

    public

    JsRequestManager(Context context,boolean isSaveCookie) {
        //gson默认会将 "123"解析为123.0 Double类型.需要注册一个适配器来解决.
//        mGson_sharedJsonParser = new GsonBuilder().registerTypeAdapter( new TypeToken<TreeMap<String, Object>>(){}.getType(),
//                new JsonDeserializer<TreeMap<String, Object>>() {
//                    @Override
//                    public TreeMap<String, Object> deserialize(
//                            JsonElement json, Type typeOfT,
//                            JsonDeserializationContext context) throws JsonParseException {
//
//                        TreeMap<String, Object> treeMap = new TreeMap<>();
//                        JsonObject jsonObject = json.getAsJsonObject();
//                        Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
//                        for (Map.Entry<String, JsonElement> entry : entrySet) {
//                            treeMap.put(entry.getKey(), entry.getValue());
//                        }
//                        return treeMap;
//                    }
//                }).create();

        mGson_sharedJsonParser =  new GsonBuilder().registerTypeAdapter(new TypeToken<Map<String, Object>>() {
        }.getType(), new JsJsonManager.MapTypeAdapter()).create();

        mContext = context;

        mSpManager = new JsSharedPreferencesManager(context,"JsRequestManager");
        if(isSaveCookie) {
            restoreCookiesFromEp();
        }
    }

    //清除所有的cookie
    public void clearAllCookies() {
        mMap_cookieStore.clear();
    }

    //添加cookie
    public void setCookies(String host,List<Cookie> cookies) {
        mMap_cookieStore.put(host,cookies);

    }


    public void saveCookiesToEp() {
        if(!mMap_cookieStore.isEmpty()) {
            String cookiesJson = mGson_sharedJsonParser.toJson(mMap_cookieStore);
            mSpManager.set(cookiesKey,cookiesJson);
        }
    }

    private void restoreCookiesFromEp() {
        String cookiesJson = mSpManager.get(cookiesKey);
        if(cookiesJson.length() > 0) {
            Type type = new TypeToken<HashMap<String, List<Cookie>>>(){}.getType();
            HashMap<String, List<Cookie>> map = JsJsonManager.fromJson(cookiesJson,type);
            mMap_cookieStore = map;
        }

    }


    public List<Cookie> cookiesForHost(String host) {
        return mMap_cookieStore.get(host);
    }

    public class RetryIntercepter implements Interceptor {

        public int maxRetry;//最大重试次数
        private int retryNum = 0;//假如设置为3次重试的话，则最大可能请求4次（默认1次+3次重试）

        public RetryIntercepter(int maxRetry) {
            this.maxRetry = maxRetry;
        }

        //GaMark:这里有异常就需要抛出来,返回值必须非空...
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Response response = null;
            response = chain.proceed(request);

            while ((response == null || !response.isSuccessful()) && retryNum < maxRetry) {
                retryNum++;
                if(retryNum > 0) {
                    System.out.println("retryNum=" + retryNum);
                }
                response = chain.proceed(request);
            }
            //返回整个流程就结束了.//返回null报错?
            return response;
        }
    }





    private OkHttpClient defaultClient() {
        if(mDefaultClient == null) {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();

            //1/4 自动存储cookie
            /**
             * 估计每一次请求,都会进行处理,将该url对应的host和cookies存起来到这个map中.
             * 然后每次发起请求时,都会先去查询是否有cookie,有的话就添加到header中.
             */
            builder.cookieJar(new CookieJar() {

                @Override
                public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                    String host = url.host();
                    mMap_cookieStore.put(host, cookies);
                    //将cookie保存到本地
                    if(mb_isSaveCookieToEp) {
                        saveCookiesToEp();
                    }
                }

                @Override
                public List<Cookie> loadForRequest(HttpUrl url) {
                    List<Cookie> cookies = mMap_cookieStore.get(url.host());
                    return cookies != null ? cookies : new ArrayList<Cookie>();
                }
            });

            //2/4 允许https证书无效
            // Create a trust manager that does not validate certificate chains
            X509TrustManager x509TrustManager =  new X509TrustManager() {
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                }

                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                }

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[]{};
                }
            };
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    x509TrustManager
            };

            // Install the all-trusting trust manager
            SSLContext sslContext = null;
            try {
                sslContext = SSLContext.getInstance("SSL");
                sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            builder.sslSocketFactory(sslSocketFactory,x509TrustManager);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });

            // 3/4 基本设置
            //连接超时时间
            builder.connectTimeout(10, TimeUnit.SECONDS);
            //设置读取超时时间
            builder.readTimeout(20, TimeUnit.SECONDS);



            // 4/4 允许http访问
            //3次重试
            builder.addInterceptor(new RetryIntercepter(3));


            mDefaultClient = builder.build();


        }
        return mDefaultClient;
    }


    //1 Get
    //1.1 异步请求
    //1.1.1 异步-字典参数-字典结果
    public void getRequest(final String interfaceUrlString, Map<String, String> map_param, final JsRequestDictionaryCallback dictionaryCallback) {
        getRequest(interfaceUrlString, map_param, new JsRequestStringCallback() {
            @Override
            public void onRequestResponse(int responseCode, String resultObject, String detailInfo) {
                final Map resultMap = mGson_sharedJsonParser.fromJson(resultObject,new TypeToken<Map<String, Object>>(){}.getType());
                //返回到主线程.
                dictionaryCallback.onRequestResponse(responseCode,resultMap,detailInfo);
            }
        });
    }

    //1.1.2 异步-字典参数-字符串结果
    public void getRequest(final String interfaceUrlString, Map<String, String> map_param,Map<String,String> map_header,final JsRequestStringCallback callback) {
        //获取请求地址
        final String requestUrl = getRequestUrlString(interfaceUrlString,map_param);
        //1 创建请求
        Request.Builder requestBuilder = new Request.Builder();
        if(map_header != null ) {
            for (String key : map_header.keySet()) {
                try {
                    String value = map_header.get(key);
                    requestBuilder.addHeader(key, value);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        final Request reqeust = requestBuilder.url(requestUrl).build();

        //2 创建客户端
        OkHttpClient client = defaultClient();


        //3 请求
        client.newCall(reqeust).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                callback.onRequestResponse(-1,null,"请检查网络");
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull final Response response) throws IOException {
                ResponseBody body = response.body();
                final int responseCode = response.code();
                final String jsonResult = body.string();
                final String interfaceDetail = String.format("\n   \n+++ Request info start +++\nReqeust url: %s\nReqeust method: %s\nReqeust param: %s\nRequest response: %s\n=== Request info end ===\n",requestUrl,"get","",jsonResult);
                JsThreadManager.runInMainThread(0, true, new Runnable() {
                    @Override
                    public void run() {
                        callback.onRequestResponse(responseCode,jsonResult,interfaceDetail);
                        response.close();
                    }
                });
            }
        });
    }
    public void getRequest(final String interfaceUrlString, Map<String, String> map_param, final JsRequestStringCallback callback) {
       getRequest(interfaceUrlString,map_param,null,callback);
    }

    //1.1.3 异步-字典参数-字典结果
    public void getRequestWithHeader(String urlString, Map<String, String> map_param, Map<String,String>map_header,final JsRequestStringCallback callback) {
        // 0 拼接url
        StringBuilder sb_paramPart = new StringBuilder();
        int pos = 0;
        for (String key : map_param.keySet()) {
            if (pos > 0) {
                sb_paramPart.append("&");
            }
            //对参数进行URLEncoder
            try {
                sb_paramPart.append(String.format("%s=%s", key, URLEncoder.encode(map_param.get(key), "utf-8")));
            } catch (Exception e) {
                e.printStackTrace();
            }
            pos++;
        }
        //补全请求地址
        final String requestUrl = String.format("%s?%s", urlString, sb_paramPart.toString());
        //1 创建请求
        Request.Builder requestBuilder = new Request.Builder();
        for (String key : map_header.keySet()) {
            try {
                String value = map_header.get(key);
                requestBuilder.addHeader(key,value);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        final Request reqeust = requestBuilder.url(requestUrl).build();


        //2 创建客户端
        OkHttpClient client = defaultClient();


        //3 请求
        client.newCall(reqeust).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                callback.onRequestResponse(-1,null,"请检查网络");
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull final Response response) throws IOException {
                ResponseBody body = response.body();
                final int responseCode = response.code();
                final String jsonResult = body.string();
                final String interfaceDetail = String.format("\n   \n+++ Request info start +++\nReqeust url: %s\nReqeust method: %s\nReqeust param: %s\nRequest response: %s\n=== Request info end ===\n",requestUrl,"get","",jsonResult);
                JsThreadManager.runInMainThread(0, true, new Runnable() {
                    @Override
                    public void run() {
                        callback.onRequestResponse(responseCode,jsonResult,interfaceDetail);
                        response.close();
                    }
                });
            }
        });
    }

    //1.2.1 异步-字符串参数.
    @Override
    public void getRequest(final String url, final String requestBodyString, final JsRequestStringCallback cb) {

    }

    //1.3 同步请求
    public Response getRequestSync(final String interfaceUrlString, final Map<String, String> requestParamMap) throws IOException {
        //获取请求地址
        String requestUrlString = getRequestUrlString(interfaceUrlString,requestParamMap);
        //1 创建请求
        final Request reqeust = new Request.Builder().url(requestUrlString).build();

        //2 创建客户端
        OkHttpClient client = defaultClient();


        //3 请求
        return client.newCall(reqeust).execute();
    }

    /**
     * 获取Get请求的ReqeustUrlString
     * @param interfaceUrlString
     * @param requestParamMap
     * @return
     */
    public String getRequestUrlString(String interfaceUrlString, Map<String, String> requestParamMap) {
        if(requestParamMap != null && requestParamMap.size() > 0) {
            StringBuilder sb_paramPart = new StringBuilder();
            int pos = 0;
            for (String key : requestParamMap.keySet()) {
                if (pos > 0) {
                    sb_paramPart.append("&");
                }
                //对参数进行URLEncoder
                try {
                    sb_paramPart.append(String.format("%s=%s", key, URLEncoder.encode(requestParamMap.get(key), "utf-8")));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                pos++;
            }
            //请求参数
            final String queryString = sb_paramPart.toString();
            return  String.format("%s?%s",interfaceUrlString,queryString);
        }
        else {
            return interfaceUrlString;
        }

    }


    public void uploadFile(final String urlString, Map<String, String> map_param, final String filePath, String fileName, String fileSize, final JsRequestUploadProgressCallback progressCallback, final JsRequestStringCallback callback) {
        OkHttpClient client = new OkHttpClient.Builder().build();


        // 0 拼接url
        StringBuilder sb_paramPart = new StringBuilder();
        int pos = 0;
        for (String key : map_param.keySet()) {
            if (pos > 0) {
                sb_paramPart.append("&");
            }
            //对参数进行URLEncoder
            try {
                sb_paramPart.append(String.format("%s=%s", key, URLEncoder.encode(map_param.get(key), "utf-8")));
            }
            catch (Exception e){
                e.printStackTrace();
            }
            pos++;
        }
        //补全请求地址
        final String str_requestParam = sb_paramPart.toString();
        String requestUrl = String.format("%s?%s", urlString, str_requestParam);

        final File file = new File(filePath);
        RequestBody requestBody = new RequestBody() {
            @Nullable
            @Override
            public MediaType contentType() {
                return MediaType.parse("text/html;charset=utf-8");
            }

            @Override
            public void writeTo(@NotNull BufferedSink bufferedSink) throws IOException {
                Source source;
                try {
                    source = Okio.source(file);
                    bufferedSink.writeAll(source);
                    //sink.writeAll(source);
//                    Buffer buf = new Buffer();
//                    Long remaining = contentLength();
//                    for (long readCount; (readCount = source.read(buf, 2048)) != -1; ) {
//                        bufferedSink.write(buf, readCount);
//                        progressCallback.onUploadProgressResponse(contentLength(), remaining -= readCount, remaining == 0);
//                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };


        Request.Builder requestBuilder = new Request.Builder();
        //设置url
        requestBuilder.url(requestUrl);
        //设置header
        String str_range = String.format("bytes 0-%s/%s",fileSize,fileSize);
        requestBuilder.header("Content-Range",str_range);
        //设置body
        requestBuilder.post(requestBody);
        //构建请求
        Request request = requestBuilder.build();

        //3 请求
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                callback.onRequestResponse(-1,null,e.getLocalizedMessage());
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                ResponseBody body = response.body();
                String jsonResult = body.string();
                String interfaceDetail = String.format("\n   \n+++ Request info start +++\nReqeust url: %s\nReqeust method: %s\nReqeust param: %s\nRequest response: %s\n=== Request info end ===\n",urlString,"post",str_requestParam,jsonResult);
                callback.onRequestResponse(200,jsonResult,interfaceDetail);
            }
        });
    }


    //2 Post
    //2.1 post application/json
    //2.1.1 post application/json map参数 异步
    //异步请求
    @Override
    public void postReqeustByJson(String url, Map map_param, final JsRequestDictionaryCallback dictionaryCallback) {
        String str_param = mGson_sharedJsonParser.toJson(map_param);
        JsRequestStringCallback cb = new JsRequestStringCallback() {
            @Override
            public void onRequestResponse(final int responseCode, String resultObject, final String detailInfo) {
//                Map resultMap = mGson_sharedJsonParser.fromJson(result,Map.class);
//                Map resultMap = mGson_sharedJsonParser.fromJson(result,new TypeToken<TreeMap<String, Object>>(){}.getType());
                final Map resultMap = mGson_sharedJsonParser.fromJson(resultObject,new TypeToken<Map<String, Object>>(){}.getType());

                //返回到主线程.
                dictionaryCallback.onRequestResponse(responseCode,resultMap,detailInfo);
            }
        };
        postReqeustByJson(url,str_param,cb);
    }

    //2.1.2 发起post请求,回调的数据参数为body的字符串内容.
    public void postReqeustByJson(final String urlString, final String requestJson, final JsRequestStringCallback callback) {
        //1 创建请求
        //MediaType  设置Content-Type 标头中包含的媒体类型值
        RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8")
                , requestJson);
        final Request reqeust = new Request.Builder().url(urlString).method("POST",requestBody).build();

        //2 创建客户端
        OkHttpClient client = defaultClient();

        //3 请求
        client.newCall(reqeust).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                JsThreadManager.runInMainThread(0, true, new Runnable() {
                    @Override
                    public void run() {
                        callback.onRequestResponse(-1,null,"请检查网络");
                    }
                });



            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                ResponseBody body = response.body();
                final int responseCode = response.code();
                final String jsonResult = body.string();

                final String interfaceDetail = String.format("\n   \n+++ Request info start +++\nReqeust url: %s\nReqeust method: %s\nReqeust param: %s\nRequest response: %s\n=== Request info end ===\n",urlString,"post",requestJson,jsonResult);


                JsThreadManager.runInMainThread(0, true, new Runnable() {
                    @Override
                    public void run() {
                        callback.onRequestResponse(responseCode,jsonResult,interfaceDetail);
                    }
                });


            }
        });
    }




    //2.1.3 post application/json string参数 同步
    public Response postRequestSyncByJson(final String interfaceUrlString, String requestParamString) throws IOException {
        //1 创建请求
        //MediaType  设置Content-Type 标头中包含的媒体类型值
        MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8")
                , requestParamString);
        final Request reqeust = new Request.Builder().url(interfaceUrlString).method("POST",requestBody).build();

        //2 创建客户端
        OkHttpClient client = defaultClient();

        //3 请求
        return client.newCall(reqeust).execute();
    }

    //2.1.4 post 回调的数据参数为body的字符串内容 和 header数据.
    public void postReqeustByJson2(final String urlString, final String requestJson, final JsRequestCallback2 callback) {
        //1 创建请求
        //MediaType  设置Content-Type 标头中包含的媒体类型值
        RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8")
                , requestJson);
        final Request reqeust = new Request.Builder().url(urlString).method("POST",requestBody).build();

        //2 创建客户端
        OkHttpClient client = defaultClient();

        //3 请求
        client.newCall(reqeust).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                JsThreadManager.runInMainThread(0, true, new Runnable() {
                    @Override
                    public void run() {
                        callback.onRequestResponse(-1,null,null,"请检查网络");
                    }
                });



            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                ResponseBody body = response.body();
                final int responseCode = response.code();
                final String jsonResult = body.string();
                final String responseHeaderString = response.headers().toString();
                final Map responseHeaderMap = response.headers().toMultimap();

                StringBuilder sb = new StringBuilder();
                sb.append("\n\n+++ Request info start +++\n");
                sb.append(String.format("Reqeust url: %s\n", urlString));
                sb.append(String.format("Reqeust method: %s\n", "POST"));
                sb.append(String.format("Response body: %s\n", requestJson));
                sb.append(String.format("Response header: %s\n", responseHeaderString));
                sb.append("=== Request info start ===\n\n");
                final String interfaceDetail = sb.toString();

                JsThreadManager.runInMainThread(0, true, new Runnable() {
                    @Override
                    public void run() {
                        callback.onRequestResponse(responseCode,jsonResult,responseHeaderMap,interfaceDetail);
                    }
                });
            }
        });
    }

    //2.1.5 post 回调的数据参数为body的字符串内容 和 header数据.
    public void postReqeustByJson2(final String urlString, final Map map_param, final JsRequestDictionaryCallback2 callback) {
        String str_param = mGson_sharedJsonParser.toJson(map_param);
        //1 创建请求
        //MediaType  设置Content-Type 标头中包含的媒体类型值
        RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8")
                , str_param);
        JsRequestCallback2 cb = new JsRequestCallback2() {
            @Override
            public void onRequestResponse(final int responseCode, String responseBodyString,Map responseHeaderMap, final String detailInfo) {

                final Map responseBodyMap = mGson_sharedJsonParser.fromJson(responseBodyString,new TypeToken<Map<String, Object>>(){}.getType());

                //返回到主线程.
                callback.onRequestResponse(responseCode,responseBodyMap,responseHeaderMap,detailInfo);
            }
        };
        postReqeustByJson2(urlString,str_param,cb);
    }

    //2.2.1 post application/x-www-form-urlencoded
    public void postReqeustByUrlencoded(final String urlString, Map map_param, final JsRequestDictionaryCallback callback) {
        //1 创建请求体数据.
        FormBody.Builder formBodyBuilder = new FormBody.Builder();

        //1.2 遍历和导入.
        Set<Map.Entry<String, String>> entrySet = map_param.entrySet();
        for (Map.Entry<String, String> entry : entrySet) {
            formBodyBuilder.add(entry.getKey(),entry.getValue());
        }
        final String str_param = mGson_sharedJsonParser.toJson(map_param);

        //2 构建Request
        Request request = new Request.Builder().url(urlString).post(formBodyBuilder.build()).build();

        //3 创建call
        Call call = defaultClient().newCall(request);

        //4 发起请求设置回调
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                JsThreadManager.runInMainThread(0, true, new Runnable() {
                    @Override
                    public void run() {
                        callback.onRequestResponse(-1,null,"请检查网络");
                    }
                });
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                ResponseBody body = response.body();
                final int responseCode = response.code();

                //字符串结果转化为字典
                //如果不是一个标准的json,则建立一个key=rawString,value=string的键值对.
                final String str_result = body.string();
                Map resultMap;
                final Map finalResultMap;
                try {
                    resultMap = mGson_sharedJsonParser.fromJson(str_result, new TypeToken<Map<String, Object>>() {
                    }.getType());
                }
                catch (Exception e) {
                    resultMap = new HashMap();
                    resultMap.put("rawString",str_result);
                }
                finalResultMap = resultMap;

                final String interfaceDetail = String.format("\n"+
                        "+++ Request info start +++\n" +
                        "Reqeust url: %s\n" +
                        "Reqeust method: %s\n" +
                        "Content type: application/x-www-urlencoded\n" +
                        "Reqeust param: %s\n" +
                        "Request response: %s\n" +
                        "=== Request info end ===\n",urlString,"post",str_param,str_result);


                JsThreadManager.runInMainThread(0, true, new Runnable() {
                    @Override
                    public void run() {
                        callback.onRequestResponse(responseCode,finalResultMap,interfaceDetail);
                    }
                });
            }
        });
    }

    //2.3.1 post multipart/form-data
    public void postReqeustByForm(final String interfaceUrlString, Map map_param, final JsRequestDictionaryCallback cb) {

//        RequestBody requestBody = new MultipartBody.Builder()
//                .setType(MultipartBody.FORM)
//                .addFormDataPart("file", fileName,
//                        new RequestBody() {
//
//                            public File mFile = new File(filePath);
//
//                            @Override
//                            public MediaType contentType() {
//                                return MultipartBody.FORM;
//                            }
//
//                            @Override
//                            public long contentLength() {
//                                return mFile.length();
//                            }
//
//                            @Override
//                            public void writeTo(BufferedSink sink) throws IOException {
//                                Source source;
//                                try {
//                                    source = Okio.source(mFile);
//                                    //sink.writeAll(source);
//                                    Buffer buf = new Buffer();
//                                    Long remaining = contentLength();
//                                    for (long readCount; (readCount = source.read(buf, 2048)) != -1; ) {
//                                        sink.write(buf, readCount);
//                                        progressCallback.onUploadProgressResponse(contentLength(), remaining -= readCount, remaining == 0);
//                                    }
//                                } catch (Exception e) {
//                                    e.printStackTrace();
//                                }
//                            }
//                        })
//                .build();
    }

    //2.4.1 raw
    public void postReqeustByRaw(final String interfaceUrlString, Map map_param, final JsRequestDictionaryCallback cb) {

    }


}